View Javadoc
1   package edu.jiangxin.apktoolbox.swing.extend.filepanel;
2   
3   import edu.jiangxin.apktoolbox.utils.Constants;
4   import edu.jiangxin.apktoolbox.utils.FileUtils;
5   import org.apache.commons.lang3.ArrayUtils;
6   import org.apache.commons.lang3.StringUtils;
7   import org.apache.logging.log4j.LogManager;
8   import org.apache.logging.log4j.Logger;
9   
10  import javax.swing.*;
11  import javax.swing.filechooser.FileNameExtensionFilter;
12  import java.awt.*;
13  import java.awt.datatransfer.DataFlavor;
14  import java.awt.datatransfer.Transferable;
15  import java.awt.datatransfer.UnsupportedFlavorException;
16  import java.awt.event.ActionEvent;
17  import java.awt.event.ActionListener;
18  import java.io.File;
19  import java.io.IOException;
20  import java.io.Serial;
21  import java.util.List;
22  
23  public class FilePanel extends JPanel {
24      @Serial
25      private static final long serialVersionUID = 1L;
26  
27      private static final Logger LOGGER = LogManager.getLogger(FilePanel.class.getSimpleName());
28      private JTextField fileTextField;
29  
30      private String buttonText;
31  
32      private String currentDirectoryPath = ".";
33  
34      private int fileSelectionMode = JFileChooser.FILES_ONLY;
35  
36      private String description;
37  
38      private String[] extensions;
39  
40      private JFileChooser fileChooser;
41  
42      private transient IFileReadyCallback callback;
43  
44      public FilePanel(String buttonText) {
45          super();
46          fileChooser = new JFileChooser();
47          this.buttonText = buttonText;
48      }
49  
50      // in case of escape of "this"
51      public void initialize() {
52          initUI();
53      }
54  
55      public void setCurrentDirectoryPath(String currentDirectoryPath) {
56          this.currentDirectoryPath = currentDirectoryPath;
57      }
58  
59      public void setPersistentKey(String persistentKey) {
60          fileTextField.setName(persistentKey);
61      }
62  
63      public void setFileReadyCallback(IFileReadyCallback callback) {
64          this.callback = callback;
65      }
66  
67      public void setFileSelectionMode(int fileSelectionMode) {
68          this.fileSelectionMode = fileSelectionMode;
69      }
70  
71      public void setDescriptionAndFileExtensions(String description, String[] extensions) {
72          this.description = description;
73          this.extensions = extensions;
74          if (StringUtils.isNotEmpty(description) || ArrayUtils.isNotEmpty(extensions)) {
75              FileNameExtensionFilter filter = new FileNameExtensionFilter(description, extensions);
76              if (fileChooser != null) {
77                  fileChooser.resetChoosableFileFilters();
78                  fileChooser.addChoosableFileFilter(filter);
79                  fileChooser.setAcceptAllFileFilterUsed(false);
80              }
81          } else {
82              if (fileChooser != null) {
83                  fileChooser.resetChoosableFileFilters();
84                  fileChooser.setAcceptAllFileFilterUsed(true);
85              }
86          }
87      }
88  
89      private void initUI() {
90          setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
91  
92          fileTextField = new JTextField();
93          fileTextField.setPreferredSize(new Dimension(600, 30));
94          fileTextField.setMaximumSize(new Dimension(1200, 30));
95          fileTextField.setTransferHandler(new FileTransferHandler());
96  
97          JButton chooseButton = new JButton(buttonText);
98          chooseButton.addActionListener(new OpenDictionaryFileActionListener());
99  
100         add(fileTextField);
101         add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
102         add(chooseButton);
103     }
104 
105     public File getFile() {
106         return new File(fileTextField.getText());
107     }
108 
109     class OpenDictionaryFileActionListener implements ActionListener {
110         @Override
111         public void actionPerformed(ActionEvent e) {
112             fileChooser.setCurrentDirectory(new File(currentDirectoryPath));
113             fileChooser.setFileSelectionMode(fileSelectionMode);
114             fileChooser.setMultiSelectionEnabled(false);
115             if (StringUtils.isNotEmpty(description) || ArrayUtils.isNotEmpty(extensions)) {
116                 FileNameExtensionFilter filter = new FileNameExtensionFilter(description, extensions);
117                 fileChooser.addChoosableFileFilter(filter);
118                 fileChooser.setAcceptAllFileFilterUsed(false);
119             } else {
120                 fileChooser.resetChoosableFileFilters();
121                 fileChooser.setAcceptAllFileFilterUsed(true);
122             }
123             int returnVal = fileChooser.showOpenDialog(FilePanel.this);
124             if (returnVal == JFileChooser.APPROVE_OPTION) {
125                 File selectedFile = fileChooser.getSelectedFile();
126                 fileTextField.setText(FileUtils.getCanonicalPathQuiet(selectedFile));
127                 if (callback != null) {
128                     callback.onFileReady(selectedFile);
129                 }
130             }
131         }
132     }
133 
134     class FileTransferHandler extends TransferHandler {
135         @Serial
136         private static final long serialVersionUID = 1L;
137 
138         public FileTransferHandler() {
139         }
140 
141         @Override
142         public boolean importData(JComponent comp, Transferable t) {
143             List<File> files = null;
144             try {
145                 @SuppressWarnings("unchecked")
146                 List<File> tmp = (List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
147                 files = tmp;
148             } catch (IOException e) {
149                 LOGGER.error("importData failed: IOException");
150             } catch (UnsupportedFlavorException e) {
151                 LOGGER.error("importData failed: UnsupportedFlavorException");
152             }
153             if (files == null || files.size() != 1) {
154                 LOGGER.error("importData failed: getTransferData failed");
155                 return false;
156             }
157             File file = files.get(0);
158             if ((!file.isFile() && fileSelectionMode == JFileChooser.FILES_ONLY)
159                     ||(!file.isDirectory() && fileSelectionMode == JFileChooser.DIRECTORIES_ONLY)) {
160                 LOGGER.error("importData failed: fileSelectionMode is not match");
161                 return false;
162             }
163             fileTextField.setText(FileUtils.getCanonicalPathQuiet(file));
164             if (callback != null) {
165                 callback.onFileReady(file);
166             }
167             return true;
168         }
169 
170         @Override
171         public boolean canImport(JComponent jComponent, DataFlavor[] dataFlavors) {
172             for (DataFlavor dataFlavor : dataFlavors) {
173                 if (DataFlavor.javaFileListFlavor.equals(dataFlavor)) {
174                     return true;
175                 }
176             }
177             return false;
178         }
179     }
180 }